home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * physics calculations of the model motion
- * Yossi Friedman, July 1988
- */
-
- #include <stdio.h>
- #include <gl.h>
- #include <math.h>
-
- #include "config.h"
- #include "newton.h"
- #include "slider.h"
-
- /* free physical parameters */
- float gravity; /* current gravity */
- float wall_k; /* spring constant of the walls */
- float fric; /* friction of the wall */
- float air_damp; /* air friction */
- float disp_step; /* display time increment */
-
-
-
- /* dependent physical parameters */
- static float dt; /* computation time increment */
- static float t; /* current time, modulo dt */
-
-
- float grav_vec_V[3]; /* real gravity vector (in viewing system) */
- float grav_vec[3]; /* gravity vector in modeling coord system */
-
-
- struct slider *k_slider; /* ptr. to K slider */
-
- void new_gravity(float), new_k(float),
- new_wall_k(float), new_fric(float),
- new_air_damp(float), new_disp_step(float);
-
- initialize_physics()
- {
- /* gravity vector should point down in the viewing coordinate system */
- grav_vec_V[X] = grav_vec_V[Z] = 0.;
-
- /* set the sliders properly */
- initialize_slider_parameters();
- t = 0.;
-
- stop_gravity();
- }
-
-
- initialize_slider_parameters()
- {
- struct slider *sp;
-
- sp = sliders;
-
- sp->title = "Gravity";
- sp->lo = 0.;
- sp->hi = 0.4;
- sp->dflt = 0.1;
- sp->fun = new_gravity;
-
- sp++;
-
- sp->title = "Spring Constant";
- sp->lo = 0.1;
- sp->hi = 50.;
- /* sp->dflt = max_k; */
- sp->dflt = 0.; /* dummy */
- sp->fun = new_k;
- k_slider = sp;
-
- sp++;
-
- sp->title = "Wall Stiffness";
- sp->lo = 0.01;
- #if ECLIPSE || CLOVER1 /* the slow machines */
- sp->hi = 0.8;
- sp->dflt = 0.3;
- #else /* ECLIPSE || CLOVER1 */
- sp->hi = 1.5;
- sp->dflt = 0.8;
- #endif /* ECLIPSE || CLOVER1 */
- sp->fun = new_wall_k;
-
- sp++;
-
- sp->title = "Wall Friction";
- sp->lo = 1. - 1.;
- sp->hi = 1. - 0.5;
- sp->dflt = 1. - 0.9;
- sp->fun = new_fric;
-
- sp++;
-
- sp->title = "Air Dampening";
- sp->lo = 1. - 1.;
- sp->hi = 1. - 0.99;
- sp->dflt = 1. - 0.9995;
- sp->fun = new_air_damp;
-
- sp++;
-
- sp->title = "Display Step";
- sp->lo = 1.;
- sp->hi = 7.;
- #if ECLIPSE || CLOVER1 /* the slow machines */
- sp->dflt = 6.5;
- #else /* ECLIPSE || CLOVER1 */
- sp->dflt = 3.0;
- #endif /* ECLIPSE || CLOVER1 */
- sp->fun = new_disp_step;
-
- sp++;
-
- end_sliders = sp;
- }
-
-
- void
- new_gravity(float val)
- {
- gravity = val;
- if (grav_vec_V[Y] != 0.) {
- grav_vec_V[Y] = gravity;
-
- /* get the gravity vector to point down properly */
- apply(grav_vec, grav_vec_V, M_inv);
- }
- }
-
- void
- new_k(float val)
- {
- Spring *spring;
- float k;
-
- if (val == 0.) /* dummy */
- return;
-
- for (spring = model_springs; spring < end_model_springs TOTAL; spring++)
- spring->k *= val/max_k;
-
- max_k = val;
-
- /* calculate dt */
- k = (max_k > wall_k)? max_k: wall_k;
- dt = sqrt(2./k) * 0.5; /* fifty percent thumb rule */
- }
-
- void
- new_wall_k(float val)
- {
- wall_k = val;
- }
-
- void
- new_fric(float val)
- {
- fric = 1. - val;
- }
-
- void
- new_air_damp(float val)
- {
- air_damp = 1. - val;
- }
-
- void
- new_disp_step(float val)
- {
- disp_step = val;
- }
-
-
- stop_gravity()
- {
- grav_vec[X] =
- grav_vec[Y] =
- grav_vec[Z] =
- grav_vec_V[X] =
- grav_vec_V[Y] =
- grav_vec_V[Z] = 0.0;
-
- }
-
- start_gravity()
- {
- grav_vec_V[Y] = gravity;
-
- /* get the gravity vector to point down properly */
- apply(grav_vec, grav_vec_V, M_inv);
- }
-
-
- void
- set_default_k(float k)
- {
- set_slider_default(k_slider->sid, k);
- set_k(k);
- }
-
-
- void
- set_k(float k)
- {
- set_slider(k_slider->sid, k);
- }
-
-
- /*
- * rotate the physics (gravity and model atoms vectors) in the ROOM
- * coordinate system angle alpha around a VIEWING axis
- */
- rotate_physics(Angle alpha, char axis)
- {
- /* first get the gravity vector to point down properly */
- apply(grav_vec, grav_vec_V, M_inv);
-
- /*
- * the formula is:
- * v R = v M rot M_inv,
- * where rot is the rotation matrix (in the viewing system) around the
- * viewing axis.
- */
- pushmatrix();
- loadmatrix(M_inv);
- rotate(alpha, axis);
- multmatrix(M);
- getmatrix(R);
- popmatrix();
-
- SLAVE_FUNC(DO_ROTATE_PHYSICS);
- do_rotate_physics(model_atoms, end_model_atoms MASTER);
- WAIT_FOR_SLAVE();
- }
-
-
- do_rotate_physics(Atom *start, Atom *finish)
- {
- Atom *ap;
- float ov[3], *v;
-
- for (ap = start; ap < finish; ap++) {
- v = ap->pos;
- ov[X] = v[X]; ov[Y] = v[Y]; ov[Z] = v[Z];
- apply(v, ov, R);
-
- v = ap->vel;
- ov[X] = v[X]; ov[Y] = v[Y]; ov[Z] = v[Z];
- apply(v, ov, R);
- }
- }
-
-
- iterate()
- {
- if(dt <= 0.0)
- return;
-
- for (; t < disp_step; t += dt) {
- SLAVE_FUNC(DO_CLEAR);
- do_clear(model_atoms, end_model_atoms MASTER);
- WAIT_FOR_SLAVE();
-
- wall[0].penetrated = wall[1].penetrated = wall[2].penetrated =
- wall[3].penetrated = wall[4].penetrated = wall[5].penetrated = 0;
-
- wall[0].depth = wall[1].depth = wall[2].depth =
- wall[3].depth = wall[4].depth = wall[5].depth = 0;
-
- SLAVE_FUNC(DO_ACCEL);
- do_accel(model_springs, end_model_springs MASTER MASTER_PARAM);
- WAIT_FOR_SLAVE();
-
- SLAVE_FUNC(DO_BOUNDS);
- do_bounds(model_atoms, end_model_atoms MASTER);
- WAIT_FOR_SLAVE();
-
- SLAVE_FUNC(DO_VEL_DAMP_POS);
- do_vel_damp_pos(model_atoms, end_model_atoms MASTER);
- WAIT_FOR_SLAVE();
- }
-
- t -= disp_step;
- }
-
-
- do_clear(Atom *start, Atom *finish)
- {
- Atom *ap;
-
- for(ap = start; ap < finish; ap++) {
- ap->acc MASTER [X] = -grav_vec[X] * dt;
- ap->acc MASTER [Y] = -grav_vec[Y] * dt;
- ap->acc MASTER [Z] = -grav_vec[Z] * dt;
-
- #ifdef MP
-
- {
- int i;
-
- for (i = 1; i < nproc; i++) {
- ap->acc [i] [X] =
- ap->acc [i] [Y] =
- ap->acc [i] [Z] = 0.;
- }
- }
-
- #endif /* MP */
-
- }
- }
-
-
- do_accel(Spring *start, Spring *finish, CPU_PARAM_TYPE)
- {
- Spring *spring;
- float r[3], lri, a[3], F;
-
- for (spring = start; spring < finish; spring++) {
- vec_op(r, spring->from->pos, -, spring->to->pos);
-
- lri = 1. / sqrt(r[X]*r[X] + r[Y]*r[Y] + r[Z]*r[Z]);
- r[X] *= lri;
- r[Y] *= lri;
- r[Z] *= lri;
-
- F = spring->k * (1. - spring->r0*lri) * 0.5;
- /* the division by 2 above is because half the force is applied
- on each endpoint */
-
- a[X] = r[X] * F;
- a[Y] = r[Y] * F;
- a[Z] = r[Z] * F;
-
- vec_op(spring->from->acc CPU, spring->from->acc CPU, -, a);
- vec_op(spring->to->acc CPU, spring->to->acc CPU, +, a);
- }
- }
-
-
- do_bounds(Atom *start, Atom *finish)
- {
- Atom *ap;
-
- /*
- * do_wall is a tricky code that checks weather an atom penetrated a wall.
- * if it did, do_dent applies a force on the atom with a direction back into
- * the room and a magnitude proportional to the penetration depth (i.e., the
- * wall springs are linear). It also calls do_dent to record the amount of
- * dent in the wall, for when the wall is drawn.
- *
- * The room is the cube { x \in [-HEIGHT,+HEIGHT]^3 }.
- *
- * If you absolutely have to go throught this code, re-write it manually
- * for a specific wall, and notice the symmetry conditions implied for all
- * walls. Note that if the wall is on AXIS, the other two axises can
- * be obtained by (AXIS+1)%3 and (AXIS+2)%3.
- */
- #define do_wall(WALL, AXIS, sgn) \
- /* int WALL; int AXIS; sign sgn; */ \
- do { \
- float depth = 0. sgn (ap->pos[AXIS] - (0. sgn HEIGHT)); \
- \
- if (depth > 0.) { \
- \
- /* apply forces from wall */ \
- ap->acc MASTER [AXIS] -= wall_k * (0. sgn depth); \
- ap->vel[(AXIS+1)%3] *= fric; \
- ap->vel[(AXIS+2)%3] *= fric; \
- \
- /* record deepest penetration position */ \
- if ((depth - wall[WALL].depth) > \
- (TOLERANCE * TOLERANCE - 1.) * \
- HEIGHT \
- ) { \
- wall[WALL].penetrated = 1; \
- wall[WALL].atom = ap; \
- \
- wall[WALL].depth = depth; \
- } \
- } \
- } while (0)
-
- for (ap = start; ap < finish; ap++) {
- do_wall(WALL_BOTTOM, Y, -);
- do_wall(WALL_TOP, Y, +);
- do_wall(WALL_LEFT, X, -);
- do_wall(WALL_RIGHT, X, +);
- do_wall(WALL_BACK, Z, -);
- do_wall(WALL_FRONT, Z, +);
- }
-
- #undef do_wall
-
- }
-
-
- do_vel_damp_pos(Atom *start, Atom *finish)
- {
- Atom *ap;
-
- for (ap = start; ap < finish; ap++) {
-
- #ifdef MP
-
- {
- int i;
-
- for (i = 1; i < nproc; i++)
- vec_op(ap->acc MASTER, ap->acc MASTER, +, ap->acc[i]);
- }
-
- #endif /* MP */
-
- /* calculate the velocity */
-
- vec_op(ap->vel, ap->vel, +, dt * ap->acc MASTER);
-
- /* calculate air dampening */
- ap->vel[X] *= air_damp;
- ap->vel[Y] *= air_damp;
- ap->vel[Z] *= air_damp;
-
- /* calculate position */
- vec_op(ap->pos, ap->pos, +, dt * ap->vel);
- }
- }
-